home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / FILER / TARSRC.SPK / c / tapeio < prev    next >
Text File  |  1994-08-05  |  14KB  |  589 lines

  1.  
  2. /* tape input/output routines */
  3.  
  4. #include <limits.h>
  5. #include <ctype.h>
  6. #include <stdlib.h>
  7. #include "tar.h"
  8. #include "dir.h"
  9. #include "disc.h"
  10. #include "timecon.h"
  11. #include "perms.h"
  12. #include "rmt.h"
  13. #include "tapeio.h"
  14.  
  15.  
  16. static long VolFreeSpace;
  17.  
  18.  
  19. static int FreeSpace(char *FileName, int InitLen, int InitInc, int WriteMode) {
  20.   int FileHandle,reallen,len,inc;
  21.   os_error *Error;
  22.   os_regset Regs;
  23.  
  24.   do {
  25.     do {
  26.       Regs.r[0] = WriteMode ? 0x83 : 0xC3;
  27.       Regs.r[1] = (int)FileName;
  28.     } while (!chkos(os_find(&Regs)));
  29.     FileHandle = Regs.r[0];
  30.     Regs.r[0] = 6;
  31.     Regs.r[1] = FileHandle;
  32.     len = InitLen;
  33.     reallen = InitLen;
  34.     inc = InitInc;
  35.     do {
  36.       Regs.r[2] = len + inc;
  37.       Error = os_args(&Regs);
  38.       if (Error == NULL) {
  39.         fprintf(stderr,"\rFree Space = %d",reallen);
  40.         reallen = Regs.r[2];
  41.         len = len + inc;
  42.         if (reallen < len)
  43.           inc = 0;
  44.       } else {
  45.         inc = 0;
  46.       }
  47.     } while (inc > 0);
  48.     do {
  49.       Regs.r[0] = 0;
  50.       Regs.r[1] = FileHandle;
  51.     } while (!chkos(os_find(&Regs)));
  52.     InitInc /= 4;
  53.     InitLen = reallen;
  54.   } while (InitInc >= 1024);
  55.   if (WriteMode) {
  56.     do {
  57.       Regs.r[0] = 11;
  58.       Regs.r[1] = (int)FileName;
  59.       Regs.r[2] = tarFileType;
  60.       Regs.r[4] = 0;
  61.       Regs.r[5] = reallen;
  62.     } while (!chkos(os_swix(OS_File,&Regs)));
  63.   }
  64.   fprintf(stderr,"\rFree Space = %d\n",reallen);
  65.   return reallen;
  66. } /* FreeSpace */
  67.  
  68.  
  69. static void WriteDiscHeader(int DiscNo) {
  70.   Block_t vblock;
  71.  
  72.   memset(vblock.Block, 0, RECORDSIZE);
  73.   vblock.Header.linkflag = LF_VOLHDR;
  74.   sprintf(vblock.Header.name,"Volume #%d",DiscNo);
  75.   sprintf(vblock.Header.chksum, "%6o", checksum(&vblock));
  76.   writetape(vblock.Block);
  77. } /* WriteDiscHeader */
  78.  
  79.  
  80. static void OpenArchiveFile(int WriteMode) {
  81.   char *mode;
  82.   char answer;
  83.  
  84.   if (!WriteMode) {
  85.     mode = "rb";
  86.   } else {
  87.     if (CreateArchive)
  88.       mode = "wb";
  89.     else
  90.       mode = "rb+";
  91.   }
  92.   while ((ArchiveFD = fopen(ArchiveName, mode)) == NULL) {
  93.     fprintf(stderr, "tar: cannot open %s\n", ArchiveName);
  94.     if (!QuietExecution) {
  95.       fprintf(stderr, "tar: retry? ");
  96.       answer = Decision('y');
  97.     }
  98.     if (QuietExecution || answer == 'n' || answer == 'N') {
  99.       Terminate(8);
  100.     }
  101.   }
  102.   ArchiveOpen = 1;
  103. } /* OpenArchiveFile */
  104.  
  105.  
  106. static void OpenArchiveRMT(int WriteMode) {
  107.   int mode;
  108.   char answer;
  109.  
  110.   if (!WriteMode) {
  111.     mode = O_RDONLY;
  112.   } else {
  113.     if (CreateArchive)
  114.       mode = O_CREAT | O_WRONLY;
  115.     else
  116.       mode = O_APPEND | O_RDWR;
  117.   }
  118.   while ((rmt_fd = rmtopen(ArchiveName,mode,0666)) == NULL) {
  119.     fprintf(stderr, "tar: cannot open %s\n", ArchiveName);
  120.     if (!QuietExecution) {
  121.       fprintf(stderr, "tar: retry? ");
  122.       answer = Decision('y');
  123.     }
  124.     if (QuietExecution || answer == 'n' || answer == 'N') {
  125.       Terminate(8);
  126.     }
  127.   }
  128.   ArchiveOpen = 1;
  129. } /* OpenArchiveRMT */
  130.  
  131.  
  132. static void NewTape(int WriteMode) {
  133.   recno =0;
  134.   first = 0;
  135.   switch (tapedevice) {
  136.     case tapedevice_DISC:
  137.       InitDisc();
  138.       break;
  139.     case tapedevice_FILE:
  140.       VolFreeSpace = INT_MAX;
  141.       if (MultipleVolumes) {
  142.         if (AppendToArchive)
  143.           VolFreeSpace = FreeSpace(ArchiveName,0,512000,WriteMode);
  144.         else
  145.           VolFreeSpace = INT_MAX;
  146.       }
  147.       OpenArchiveFile(WriteMode);
  148.       break;
  149.     case tapedevice_RMT:
  150.       VolFreeSpace = INT_MAX;
  151.       OpenArchiveRMT(WriteMode);
  152.       break;
  153.   }    
  154. } /* NewTape */
  155.  
  156.  
  157. static void WriteDiscEnd(int DiscNo) {
  158.   Block_t vblock;
  159.  
  160.   memset(vblock.Block, 0, RECORDSIZE);
  161.   vblock.Header.linkflag = LF_VOLEND;
  162.   sprintf(vblock.Header.name,"Volume #%d",DiscNo);
  163.   sprintf(vblock.Header.chksum, "%6o", checksum(&vblock));
  164.   writetape(vblock.Block);
  165. } /* WriteDiscEnd */
  166.  
  167.  
  168. static int chkchecksum(Block_t *Block) {
  169.   int SavedCheckSum;
  170.   int CalculatedCheckSum;
  171.  
  172.   sscanf(Block->Header.chksum, "%o", &SavedCheckSum);
  173.   CalculatedCheckSum = checksum(Block);
  174.   if (SavedCheckSum != CalculatedCheckSum) {
  175.     fprintf(stderr, "tar: directory checksum error (%d != %d)\n",
  176.       SavedCheckSum, CalculatedCheckSum);
  177.     if (IgnoreArchiveErrors) {
  178.       return 0;
  179.     }
  180.     Terminate(9);
  181.   }
  182.   return(1);
  183. } /* chkchecksum */
  184.  
  185.  
  186. static void ReadDiscHeader(int ExpectedDiscNo) {
  187.   int ActualDiscNo=0;
  188.   int ok;
  189.   Block_t vblock;
  190.  
  191.   do {
  192.     ok = 1;
  193.     if (ExpectedDiscNo > 1) {
  194.       fprintf(stderr,"Please insert disc #%d:",ExpectedDiscNo);
  195.       while (getchar() != '\n')
  196.         ;
  197.     }
  198.     NewTape(0);
  199.     readtape(vblock.Block);
  200.     chkchecksum(&vblock);
  201.     if (vblock.Header.linkflag != LF_VOLHDR) {
  202.       fprintf(stderr,"tar: disc header expected\n");
  203.       ok = 0;
  204.     } else {
  205.       sscanf(vblock.Header.name,"Volume #%d",&ActualDiscNo);
  206.       if (ActualDiscNo != ExpectedDiscNo) {
  207.         fprintf(stderr,"tar: discs out of sequence (disc #%d)\n",ActualDiscNo);
  208.         if (ExpectedDiscNo > 1)
  209.           ok = 0;
  210.         else {
  211.           DiscNo = ActualDiscNo;
  212.           ok = 1;
  213.         }
  214.       }
  215.     }
  216.   } while (!ok);
  217. } /* ReadDiscHeader */
  218.  
  219.  
  220. static void ChkDiscEnd(Block_t *vblock, int ExpectedDiscNo) {
  221.   int DiscNo=0;
  222.  
  223.   if (vblock->Header.linkflag != LF_VOLEND) {
  224.     fprintf(stderr,"tar: disc end expected\n");
  225.     return;
  226.   }
  227.   sscanf(vblock->Header.name,"Volume #%d",&DiscNo);
  228.   if (DiscNo != ExpectedDiscNo)
  229.     fprintf(stderr,"tar: disc end out of sequence\n");
  230.   if (MultipleVolumes && tapedevice == tapedevice_FILE) {
  231.     fclose(ArchiveFD);
  232.     ArchiveOpen = 0;
  233.   }
  234. } /* ChkDiscEnd */
  235.  
  236.  
  237. static void NextDisc() {
  238.   ChkDiscEnd(&Block,DiscNo++);
  239.   ReadDiscHeader(DiscNo);
  240. } /* NextDisc */
  241.  
  242.  
  243. void NewDisc() {
  244.   WriteDiscEnd(DiscNo++);
  245.   flushtape();
  246.   os_cli("dismount 0");
  247.   fprintf(stderr,"Please insert disc #%d:",DiscNo);
  248.   while (getchar() != '\n')
  249.     ;
  250.   if (FormatFloppies && MultipleVolumes && CreateArchive) {
  251.     FormatDisc();
  252.   }
  253.   NewTape(1);
  254.   WriteDiscHeader(DiscNo);
  255. } /* NewDisc */
  256.  
  257.  
  258. void open_writetape(void) {
  259.   char answer;
  260.  
  261.   switch (tapedevice) {
  262.     case tapedevice_DISC:
  263.       SetupDisc(driveno,format);
  264.       if (!NoDiskDestroyConfirmation && !QuietExecution) {
  265.         fprintf(stderr,
  266.           "tar: warning:\a data on drive %d will be overwritten!\n", driveno);
  267.         fprintf(stderr, "tar: continue? ");
  268.         answer = Decision('n');
  269.         if (answer == 'n' || answer == 'N') {
  270.           Terminate(10);
  271.         }
  272.       }
  273.       if (FormatFloppies && MultipleVolumes && CreateArchive) {
  274.         FormatDisc();
  275.       }
  276.       if (MultipleVolumes && CreateArchive) {
  277.         WriteDiscHeader(DiscNo);
  278.       }
  279.       break;
  280.     case tapedevice_FILE:
  281.       if (FormatFloppies && MultipleVolumes && CreateArchive) {
  282.         FormatDisc();
  283.       }
  284.       if (MultipleVolumes)
  285.         VolFreeSpace = FreeSpace(ArchiveName,0,512000,1);
  286.       else
  287.         VolFreeSpace = INT_MAX;
  288.       OpenArchiveFile(1);
  289.       if (MultipleVolumes && CreateArchive) {
  290.         WriteDiscHeader(DiscNo);
  291.       }
  292.       break;
  293.     case tapedevice_RMT:
  294.       VolFreeSpace = INT_MAX;
  295.       OpenArchiveRMT(1);
  296.       if (MultipleVolumes && CreateArchive) {
  297.         WriteDiscHeader(DiscNo);
  298.       }
  299.       break;
  300.   }
  301. } /* open_writetape */
  302.  
  303.  
  304. void open_readtape(void) {
  305.   switch (tapedevice) {
  306.     case tapedevice_DISC:
  307.       SetupDisc(driveno,format);
  308.       break;
  309.     case tapedevice_FILE:
  310.       VolFreeSpace = INT_MAX;
  311.       OpenArchiveFile(0);
  312.       break;
  313.     case tapedevice_RMT:
  314.       VolFreeSpace = INT_MAX;
  315.       OpenArchiveRMT(0);
  316.       break;
  317.   }
  318. } /* open_readtape */
  319.  
  320.  
  321. int checksum(Block_t *Block) {
  322.   int i;
  323.   char *cp;
  324.  
  325.   for (cp = Block->Header.chksum; cp < &Block->Header.chksum[sizeof(Block->Header.chksum)]; cp++)
  326.     *cp = ' ';
  327.   i = 0;
  328.   for (cp = Block->Block; cp < &Block->Block[RECORDSIZE]; cp++)
  329.     i += *cp;
  330.   return (i);
  331. } /* checksum */
  332.  
  333.  
  334. static int WriteBufferBlocks(char *Buffer, int NumBlocks) {
  335.   int Written;
  336.  
  337.   switch (tapedevice) {
  338.     case tapedevice_DISC:
  339.       return WriteDisc(Buffer, (long)NumBlocks * RECORDSIZE) / RECORDSIZE;
  340.     case tapedevice_FILE:
  341.       Written = fwrite(Buffer, RECORDSIZE, NumBlocks, ArchiveFD);
  342.       if (VolFreeSpace != INT_MAX) {
  343.         VolFreeSpace -= (long)Written * (long)RECORDSIZE;
  344.       }
  345.       return Written;
  346.     case tapedevice_RMT:
  347.       Written = rmtwrite(rmt_fd, Buffer, NumBlocks * RECORDSIZE);
  348.       if (VolFreeSpace != INT_MAX) {
  349.         VolFreeSpace -= (long)Written;
  350.       }
  351.       return Written;
  352.   }
  353.   return 0;
  354. } /* WriteBufferBlocks */
  355.  
  356.  
  357. static int ReadBufferBytes(char *Buffer, int NumBytes) {
  358.   int NumRead;
  359.  
  360.   switch (tapedevice) {
  361.     case tapedevice_DISC:
  362.       return(ReadDisc(Buffer,(long)NumBytes));
  363.     case tapedevice_FILE:
  364.       NumRead = fread(Buffer, 1, NumBytes, ArchiveFD);
  365.       if (VolFreeSpace != INT_MAX) {
  366.         VolFreeSpace -= NumRead;
  367.       }
  368.       return NumRead;
  369.     case tapedevice_RMT:
  370.       NumRead = rmtread(rmt_fd, Buffer, NumBytes);
  371.       if (VolFreeSpace != INT_MAX) {
  372.         VolFreeSpace -= NumRead;
  373.       }
  374.       return NumRead;
  375.   }
  376.   return 0;
  377. } /* ReadBufferBytes */
  378.  
  379.  
  380. void flushtape(void) {
  381.   if (recno > 0 && recno < nblock) {
  382.     WriteBufferBlocks((char *)TmpBlock,recno);
  383.   }
  384.   switch (tapedevice) {
  385.     case tapedevice_DISC:
  386.       FlushDisc();
  387.       break;
  388.     case tapedevice_FILE:
  389.       fclose(ArchiveFD);
  390.       SetFileType(ArchiveName, tarFileType);
  391.       ArchiveOpen = 0;
  392.       break;
  393.     case tapedevice_RMT:
  394.       rmtclose(rmt_fd);
  395.       ArchiveOpen = 0;
  396.       break;
  397.   }
  398. } /* flushtape */
  399.  
  400.  
  401. static void writeblocks() {
  402.   if (WriteBufferBlocks((char *)TmpBlock, nblock) < nblock) {
  403.     fprintf(stderr, "tar: tape write error\n");
  404.     Terminate(11);
  405.   }
  406.   recno = 0;
  407. } /* writeblocks */
  408.  
  409.  
  410. int writetape(char *buffer) {
  411.   first = 1;
  412.   if (recno >= nblock)
  413.     writeblocks();
  414.   memcpy((char *)&TmpBlock[recno++], buffer, RECORDSIZE);
  415.   if (recno >= nblock)
  416.     writeblocks();
  417.   return(RECORDSIZE);
  418. } /* writetape */
  419.  
  420.  
  421. void putempty(void) {
  422.   char buf[RECORDSIZE];
  423.  
  424.   memset(buf, 0, sizeof (buf));
  425.   writetape(buf);
  426. } /* putempty */
  427.  
  428.  
  429. int endtape(void) {
  430.   if (IgnoreArchiveErrors) {
  431.     return 0;
  432.   }
  433.   return (Block.Header.name[0] == '\0');
  434. } /* endtape */
  435.  
  436.  
  437. static int bread(char *buf, int size) {
  438.   int count;
  439.   static int lastread = 0;
  440.  
  441.   if (!Reblock)
  442.     return (ReadBufferBytes(buf, size));
  443.  
  444.   for (count = 0; count < size; count += lastread) {
  445.     if (lastread < 0) {
  446.       if (count > 0)
  447.         return (count);
  448.       return (lastread);
  449.     }
  450.     lastread = ReadBufferBytes(buf, size - count);
  451.     buf += lastread;
  452.   }
  453.   return (count);
  454. } /* bread */
  455.  
  456.  
  457. int readtape(char *buffer) {
  458.   int NumBytesRead;
  459.  
  460.   if (recno >= nblock || first == 0) {
  461.     if ((NumBytesRead = bread((char *)TmpBlock, RECORDSIZE*nblock)) <= 0) {
  462.       fprintf(stderr, "tar: tape read error\n");
  463.       Terminate(12);
  464.     }
  465.     if ((NumBytesRead % RECORDSIZE) != 0) {
  466.       fprintf(stderr, "tar: tape blocksize error\n");
  467.       if (first == 0)
  468.         Terminate(13);
  469.     }
  470.     NumBlocksRead = NumBytesRead/RECORDSIZE;
  471.     if (first == 0) {
  472.       if (NumBlocksRead != nblock) {
  473.         fprintf(stderr, "tar: blocksize = %d\n", NumBlocksRead);
  474.         nblock = NumBlocksRead;
  475.       }
  476.     }
  477.     recno = 0;
  478.   }
  479.   first = 1;
  480.   memcpy(buffer, (char *)&TmpBlock[recno++], RECORDSIZE);
  481.   return (RECORDSIZE);
  482. } /* readtape */
  483.  
  484.  
  485. void backtape(void) {
  486.   recno--;
  487.   switch (tapedevice) {
  488.     case tapedevice_DISC:
  489.       BackDisc();
  490.       break;
  491.     case tapedevice_FILE:
  492.       fseek(ArchiveFD, -(long)RECORDSIZE * NumBlocksRead, SEEK_CUR);
  493.       break;
  494.     case tapedevice_RMT:
  495.       rmtlseek(rmt_fd,-(long)RECORDSIZE * NumBlocksRead, SEEK_CUR);
  496.       break;
  497.   }
  498. } /* backtape */
  499.  
  500.  
  501. void passtape(long Length) {
  502.   long blocks;
  503.   char buf[RECORDSIZE];
  504.  
  505.   if (Block.Header.linkflag == '1')
  506.     return;
  507.   blocks = Length;
  508.   blocks += RECORDSIZE-1;
  509.   blocks /= RECORDSIZE;
  510.   while (!UserInterrupt && blocks-- > 0)
  511.     readtape(buf);
  512. } /* passtape */
  513.  
  514.  
  515. void getdir(CatInfo *InfoBlk) {
  516.   int mode, NameLen, FileType;
  517.   int ThisDiscNo;
  518.   long mtime;
  519.  
  520. top:
  521.   readtape((char *)&Block);
  522.   if (Block.Header.name[0] == 0) {
  523.     if (IgnoreArchiveErrors) {
  524.       goto top;
  525.     } else {
  526.       return;
  527.     }
  528.   }
  529.  
  530.   if (!chkchecksum(&Block))
  531.     goto top;
  532.  
  533.   if (Block.Header.linkflag == LF_VOLEND) {
  534.     if (MultipleVolumes) {
  535.       NextDisc();
  536.     } else {
  537.       fprintf(stderr,"tar: unexpected end of disc\n");
  538.       Terminate(14);
  539.     }
  540.     return;
  541.   }
  542.   
  543.   if (Block.Header.linkflag == LF_VOLHDR) {
  544.     sscanf(Block.Header.name,"Volume #%d",&ThisDiscNo);
  545.     if (ThisDiscNo != 1) {
  546.       fprintf(stderr,"tar: unexpected disc header (disc #%d)\n",ThisDiscNo);
  547.       DiscNo = ThisDiscNo;
  548.       return;
  549.     }
  550.     MultipleVolumes = 1;
  551.     return;
  552.   }
  553.   
  554.   memset((char *)InfoBlk,0,sizeof(CatInfo));
  555.   sscanf(Block.Header.size, "%lo", &InfoBlk->Length);
  556.   if (isArchie = (strcmp(Block.Header.magic, ARC_MAGIC) == 0), isArchie) {
  557.     sscanf(Block.Header.LoadAddress, "%lo", &InfoBlk->LoadAddress);
  558.     sscanf(Block.Header.ExecAddress, "%lo", &InfoBlk->ExecAddress);
  559.     sscanf(Block.Header.Attr, "%lo", &InfoBlk->Attr);
  560.     sscanf(Block.Header.Date,"%x %lx",&InfoBlk->DateAndName[4],&InfoBlk->DateAndName);
  561.   } else {
  562.     sscanf(Block.Header.mode,"%o",&mode);
  563.     InfoBlk->Attr = unix_to_fs_perms(mode);
  564.     if (CommaFileTypes && (NameLen = strlen(Block.Header.name)) > 4 &&
  565.         Block.Header.name[NameLen - 4] == ',' &&
  566.       isxdigit(Block.Header.name[NameLen - 3]) &&
  567.       isxdigit(Block.Header.name[NameLen - 2]) &&
  568.       isxdigit(Block.Header.name[NameLen - 1])) {
  569.       FileType = (int)strtoul(Block.Header.name + NameLen - 3, NULL, 16);
  570.       Block.Header.name[NameLen - 4] = 0;
  571.     } else {
  572.       FileType = (mode & (XOWN | XOTH | XGRP)) ? ft_Absolute : ft_Text;
  573.     }
  574.     InfoBlk->LoadAddress = 0xFFF00000L | ((long)FileType << 8);
  575.     sscanf(Block.Header.mtime,"%lo",&mtime);
  576.     unix_to_fs_time((unsigned char *)&InfoBlk->DateAndName,mtime);
  577.     InfoBlk->ExecAddress = *(long *)&InfoBlk->DateAndName;
  578.     InfoBlk->LoadAddress |= InfoBlk->DateAndName[4];
  579.   }
  580.   if (Block.Header.compressed == CF_COMPRESSED)
  581.     sscanf(Block.Header.compression,"%o",&compression);
  582. } /* getdir */
  583.  
  584.  
  585. long FreeOnTape(void) {
  586.   return (tapedevice == tapedevice_DISC ? FreeOnDisc() : VolFreeSpace) -
  587.          (long)recno * (long)RECORDSIZE;
  588. } /* FreeOnTape */
  589.